<?php
/**
* Copyright (c) 2009 James Gauld <james@jamesgauld.net>
* This file is part of Scribble.
* @license http://www.scribblecms.co.uk/license.txt
*
* @package Scribble
* @subpackage Plugin
*/
use Buan\Config;
use Buan\Inflector;
use Buan\SystemLog;
class SpTemplateEditorController extends ScribbleAdminController {

	/**
	* A convenience variable - holds the config namespace under which most of this
	* plugin's settings are stored.
	*
	* @var string
	*/
	private $ns = 'ext.Scribble.plugin.SpTemplateEditor';

	/**
	* Initial template creation.
	*
	* @return ScribbleAdminView
	*/
	public function create($params) {

		// Init
		$view = new ScribbleAdminView();
		if(!$this->init($view)) {
			return $view;
		}

		// Auth: Can the user modify templates
		if(!ScribbleAuth::authorize(ScribbleSession::getUser(), 'template-editor')) {
			SystemLog::add('Sorry, you do not have the authority to create or modify templates.', SystemLog::WARNING);
			return $view;
		}

		// Determine which template parent folders can be selected to house this new
		// template
		$templatePaths = ScribbleTemplateManager::getTemplatePaths();
		$validTemplatePaths = array();
		foreach($templatePaths as $tp) {
			if(is_writeable($tp->folder)) {
				$validTemplatePaths[] = $tp;
			}
		}
		if(empty($validTemplatePaths)) {
			SystemLog::add('A new template cannot be created because none of your template paths are writeable.', SystemLog::WARNING);
			return new ScribbleAdminView();
		}
		$view->templatePaths = $validTemplatePaths;

		// Prepare view
		$view->setSource(Config::get("{$this->ns}.dir.views").'/create.tpl.php');
		$renderEngines = Config::get("{$this->ns}.templateLanguages");
		if(empty($renderEngines)) {
			SystemLog::add('You have not defined any template language options. See SpTemplateEditor::addTemplateLanguage().', SystemLog::WARNING);
			return new ScribbleAdminView();
		}
		$template = (object)array(
			'type'=>'inner',
			'name'=>'',
			'title'=>'',
			'shortdesc'=>'',
			'longdesc'=>'',
			'renderEngine'=>'',
			'templatePathIndex'=>0
		);

		// Generate template
		if(!empty($_POST)) {

			// Validate/sanitize
			$template->name = strtolower(preg_replace("/\-+/", "-", preg_replace("/[^a-z0-9]/iu", "-", $_POST['name'])));
			$template->title = $_POST['title'];
			$template->type = $_POST['type'];
			$template->renderEngine = $_POST['renderEngine'];
			$template->shortdesc = $_POST['shortdesc'];
			$template->longdesc = $_POST['longdesc'];
			$template->templatePathIndex = isset($_POST['templatePath']) && isset($validTemplatePaths[$_POST['templatePath']]) ? (int)$_POST['templatePath'] : 0;
			$templatePath = $validTemplatePaths[$template->templatePathIndex]->folder."/{$template->name}";
			$valid = TRUE;
			if($template->name=='') {
				SystemLog::add('Please provide a valid name for this template.', SystemLog::WARNING);
				$valid = FALSE;
			}
			if($template->title=='') {
				SystemLog::add('Please provide a valid title for this template.', SystemLog::WARNING);
				$valid = FALSE;
			}
			if(!isset($renderEngines[$template->renderEngine])) {
				SystemLog::add('Invalid template language has been chosen.', SystemLog::WARNING);
				$valid = FALSE;
			}
			if(file_exists($templatePath)) {
				SystemLog::add('A template with this name already exists.', SystemLog::WARNING);
				$valid = FALSE;
			}
			if(!$valid) {
			}

			// Create template folder ready to hold all new template assets
			else if(!mkdir($templatePath, 0777)) {
				SystemLog::add('Failed to create the template folder.', SystemLog::WARNING);
			}
			
			// All supplied info is valid so now generate the template assets
			else {

				// Flag file to indicate this is an editable template
				if(!file_put_contents("{$templatePath}/.editable", "Generated by the template builder")) {
					SystemLog::add('Failed to create the flag file', SystemLog::WARNING);
				}

				// Class definition
				$className = 'ScribbleTemplate_'.Inflector::lowerHyphenated_lowerCamelCaps($template->name);
				$classDef = file_get_contents(Config::get('ext.Scribble.plugin.SpTemplateEditor.dir.resources').'/template-scaffold.tpl.php');
				$classDef = str_replace('[[CLASS_NAME]]', $className, $classDef);
				$classDef = str_replace('[[LONG_DESCRIPTION]]', str_replace("\n", '\n', str_replace("\r", "", addslashes($template->longdesc))), $classDef);
				$classDef = str_replace('[[SHORT_DESCRIPTION]]', addslashes($template->shortdesc), $classDef);
				$classDef = str_replace('[[TITLE]]', addslashes($template->title), $classDef);
				$classDef = str_replace('[[TYPE]]', $template->type=='outer' ? 'OUTER' : 'INNER', $classDef);
				$classDef = str_replace('[[POST_ARRAY_INDEX]]', $template->type=='outer' ? 'outer' : 'inner', $classDef);
				$re = $renderEngines[$template->renderEngine]['genEngine'];
				$classDef = str_replace('[[VIEW_ENGINE_GENERATOR]]', is_string($re) ? "'{$re}'" : "array('{$re[0]}', '{$re[1]}')", $classDef);
				if(!file_put_contents("{$templatePath}/{$className}.php", $classDef) || !chmod("{$templatePath}/{$className}.php", 0777)) {
					SystemLog::add('Failed to generate class definition', SystemLog::WARNING);
				}

				// Front-end and populator templates
				if(file_put_contents("{$templatePath}/front-end.tpl", "") || !chmod("{$templatePath}/front-end.tpl", 0777)) {
					SystemLog::add('Failed to generate front-end template', SystemLog::WARNING);
				}
				if(file_put_contents("{$templatePath}/populator.tpl", "") || !chmod("{$templatePath}/populator.tpl", 0777)) {
					SystemLog::add('Failed to generate populator template', SystemLog::WARNING);
				}

				// Result
				SystemLog::add('Template has been generated.', SystemLog::INFO);
			}
		}

		// Result
		$view->template = $template;
		$view->renderEngines = $renderEngines;
		return $view;
	}

	/**
	* Edit a template.
	*
	* @param array Action parameters
	* @param string Template name
	* @return View
	*/
	private function edit($params, $templateName) {

		// If creating a new template, request a few details first so we can create
		// the initial files
		if($templateName=='create') {
			return $this->create();
		}

		// Init
		$view = new ScribbleAdminView();
		if(!$this->init($view)) {
			return $view;
		}

		// Auth: Can the user modify templates
		if(!ScribbleAuth::authorize(ScribbleSession::getUser(), 'template-editor')) {
			SystemLog::add('Sorry, you do not have the authority to create or modify templates.', SystemLog::WARNING);
			return $view;
		}
		$view->setSource(Config::get("{$this->ns}.dir.views").'/edit.tpl.php');

		// Load the template
		try {
			$template = ScribbleTemplateManager::getTemplateByName($templateName);
		}
		catch(ScribbleTemplateException $e) {
			Systemlog::add($e->getMessage(), SystemLog::WARNING);
			return new SribbleAdminView();
		}
		$view->template = $template;
		$renderEngines = Config::get("{$this->ns}.templateLanguages");
		if(empty($renderEngines)) {
			SystemLog::add('You have not defined any template language options. See SpTemplateEditor::addTemplateLanguage().', SystemLog::WARNING);
			return new ScribbleAdminView();
		}

		// Load the markup sources
		$populatorMarkup = file_exists($template->getBaseFolder()."/populator.tpl") ? file_get_contents($template->getBaseFolder()."/populator.tpl") : '';
		$frontendMarkup = file_exists($template->getBaseFolder()."/front-end.tpl") ? file_get_contents($template->getBaseFolder()."/front-end.tpl") : '';

		// Process
		if(!empty($_POST)) {

			// Gather
			$populatorMarkup = $_POST['markup']['populator'];
			$frontendMarkup = $_POST['markup']['frontend'];

			// Validate

			// Save
			file_put_contents($template->getBaseFolder()."/populator.tpl", $populatorMarkup);
			file_put_contents($template->getBaseFolder()."/front-end.tpl", $frontendMarkup);
			SystemLog::add('Template saved.', SystemLog::INFO);
		}

		// Result
		$view->template = $template;
		$view->renderEngines = $renderEngines;
		$view->frontendMarkup = $frontendMarkup;
		$view->populatorMarkup = $populatorMarkup;
		return $view;
	}

	/**
	* Displays a list of all templates available to this installation of Scribble.
	*
	* @param array
	* @return ScribbleAdminView
	*/
	public function index($params) {

		// Auth
		if(!ScribbleAuth::authorize(ScribbleSession::getUser(), 'template-editor')) {
			ScribbleAdminView::getGlobalView()->attachViewToSlot(new ScribbleAdminView(), 'secondary');
			SystemLog::add('Sorry, you do not have the authority to create or modify page templates.', SystemLog::WARNING);
			return new ScribbleAdminView();
		}

		// Init
		$view = new ScribbleAdminView();
		if(!$this->init($view)) {
			return $view;
		}
		$view->setSource(Config::get("{$this->ns}.dir.views").'/index.tpl.php');

		// Prepare secondary view
		$sView = new ScribbleAdminView();
		$sView->setSource(Config::get("{$this->ns}.dir.views").'/index.secondary.tpl.php');
		ScribbleAdminView::getGlobalView()->attachViewToSlot($sView, 'secondary');

		// Load all available templates
		$allTemplates = ScribbleTemplateManager::getTemplateChoices();
		$templates = array();
		foreach($allTemplates as $t) {
			if(file_exists("{$t->getBaseFolder()}/.editable")) {
				$templates[] = $t;
			}
		}
		$view->templates = $templates;

		// Result
		return $view;
	}

	/**
	* Forwards through requests to the ::edit() method.
	*
	* @param array Action parameters
	* @param string Requested action. This is the Page ID.
	* @return View
	*/
	public function unknown($params, $action) {
		return $this->edit($params, $action);
	}
}
?>